In [1]:
from IPython.display import clear_output
!pip install imutils
clear_output()

from keras.applications.vgg19 import VGG19,preprocess_input
from keras.applications.xception import Xception,preprocess_input
from keras.applications.inception_v3 import InceptionV3
from keras.applications.resnet50 import ResNet50
In [ ]:
import matplotlib
matplotlib.use("Agg")
In [2]:
import numpy as np 
from tqdm import tqdm
import cv2
import os
import shutil
import itertools
import imutils
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix

import plotly.graph_objs as go
from plotly.offline import init_notebook_mode, iplot
from plotly import tools

from keras.preprocessing.image import ImageDataGenerator
from keras.applications.vgg16 import VGG16, preprocess_input
from keras import layers
from keras.models import Model, Sequential
from keras.optimizers import Adam, RMSprop
from keras.callbacks import EarlyStopping

init_notebook_mode(connected=True)
RANDOM_SEED = 123

Right now all images are in one folder with yes and no subfolders. I will split the data into train, val and test folders which makes its easier to work for me. The new folder heirarchy will look as follows:

In [3]:
!apt-get install tree
#clear_output()
# create new folders
!mkdir TRAIN TEST VAL TRAIN/YES TRAIN/NO TEST/YES TEST/NO VAL/YES VAL/NO
!tree -d
/bin/bash: apt-get: command not found
mkdir: TRAIN: File exists
mkdir: TEST: File exists
mkdir: VAL: File exists
mkdir: TRAIN/YES: File exists
mkdir: TRAIN/NO: File exists
mkdir: TEST/YES: File exists
mkdir: TEST/NO: File exists
mkdir: VAL/YES: File exists
mkdir: VAL/NO: File exists
/bin/bash: tree: command not found
In [4]:
IMG_PATH = 'brain_tumor_dataset/'
# split the data by train/val/test
for CLASS in os.listdir(IMG_PATH):
    if not CLASS.startswith('.'):
        IMG_NUM = len(os.listdir(IMG_PATH + CLASS))
        for (n, FILE_NAME) in enumerate(os.listdir(IMG_PATH + CLASS)):
            img = IMG_PATH + CLASS + '/' + FILE_NAME
            if n < 5:
                shutil.copy(img, 'TEST/' + CLASS.upper() + '/' + FILE_NAME)
            elif n < 0.8*IMG_NUM:
                shutil.copy(img, 'TRAIN/'+ CLASS.upper() + '/' + FILE_NAME)
            else:
                shutil.copy(img, 'VAL/'+ CLASS.upper() + '/' + FILE_NAME)
In [5]:
def load_data(dir_path, img_size=(100,100)):
    """
    Load resized images as np.arrays to workspace
    """
    X = []
    y = []
    i = 0
    labels = dict()
    for path in tqdm(sorted(os.listdir(dir_path))):
        if not path.startswith('.'):
            labels[i] = path
            for file in os.listdir(dir_path + path):
                if not file.startswith('.'):
                    img = cv2.imread(dir_path + path + '/' + file)
                    X.append(img)
                    y.append(i)
            i += 1
    X = np.array(X)
    y = np.array(y)
    print(f'{len(X)} images loaded from {dir_path} directory.')
    return X, y, labels



def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.
    """
    plt.figure(figsize = (6,6))
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=90)
    plt.yticks(tick_marks, classes)
    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]

    thresh = cm.max() / 2.
    cm = np.round(cm,2)
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, cm[i, j],
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")
    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.show()
In [6]:
TRAIN_DIR = 'TRAIN/'
TEST_DIR = 'TEST/'
VAL_DIR = 'VAL/'
IMG_SIZE = (224,224)

# use predefined function to load the image data into workspace
X_train, y_train, labels = load_data(TRAIN_DIR, IMG_SIZE)
X_test, y_test, _ = load_data(TEST_DIR, IMG_SIZE)
X_val, y_val, _ = load_data(VAL_DIR, IMG_SIZE)
100%|██████████| 2/2 [00:00<00:00,  3.47it/s]
/Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages/ipykernel_launcher.py:18: VisibleDeprecationWarning:

Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray

100%|██████████| 2/2 [00:00<00:00, 45.77it/s]
100%|██████████| 2/2 [00:00<00:00, 17.62it/s]
193 images loaded from TRAIN/ directory.
10 images loaded from TEST/ directory.
50 images loaded from VAL/ directory.

Let's take a look at the distribution of classes among sets:

In [7]:
y = dict()
y[0] = []
y[1] = []
for set_name in (y_train, y_val, y_test):
    y[0].append(np.sum(set_name == 0))
    y[1].append(np.sum(set_name == 1))

trace0 = go.Bar(
    x=['Train Set', 'Validation Set', 'Test Set'],
    y=y[0],
    name='No',
    marker=dict(color='#33cc33'),
    opacity=0.7
)
trace1 = go.Bar(
    x=['Train Set', 'Validation Set', 'Test Set'],
    y=y[1],
    name='Yes',
    marker=dict(color='#ff3300'),
    opacity=0.7
)
data = [trace0, trace1]
layout = go.Layout(
    title='Count of classes in each set',
    xaxis={'title': 'Set'},
    yaxis={'title': 'Count'}
)
fig = go.Figure(data, layout)
iplot(fig)
In [8]:
def plot_samples(X, y, labels_dict, n=50):
    """
    Creates a gridplot for desired number of images (n) from the specified set
    """
    for index in range(len(labels_dict)):
        imgs = X[np.argwhere(y == index)][:n]
        j = 10
        i = int(n/j)

        plt.figure(figsize=(15,6))
        c = 1
        for img in imgs:
            plt.subplot(i,j,c)
            plt.imshow(img[0])

            plt.xticks([])
            plt.yticks([])
            c += 1
        plt.suptitle('Tumor: {}'.format(labels_dict[index]))
        plt.show()
In [9]:
plot_samples(X_train, y_train, labels, 10)

As you can see, images have different width and height and diffent size of "black corners". Since the image size for VGG-16 imput layer is (224,224) some wide images may look weird after resizing. Histogram of ratio distributions (ratio = width/height):

In [10]:
RATIO_LIST = []
for set in (X_train, X_test, X_val):
    for img in set:
        RATIO_LIST.append(img.shape[1]/img.shape[0])
        
plt.hist(RATIO_LIST)
plt.title('Distribution of Image Ratios')
plt.xlabel('Ratio Value')
plt.ylabel('Count')
plt.show()

The first step of "normalization" would be to crop the brain out of the images. I used technique which was perfectly described in pyimagesearch blog and I highly suggest to looks deeper into it.

In [11]:
def crop_imgs(set_name, add_pixels_value=0):
    """
    Finds the extreme points on the image and crops the rectangular out of them
    """
    set_new = []
    for img in set_name:
        gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        gray = cv2.GaussianBlur(gray, (5, 5), 0)

        # threshold the image, then perform a series of erosions +
        # dilations to remove any small regions of noise
        thresh = cv2.threshold(gray, 45, 255, cv2.THRESH_BINARY)[1]
        thresh = cv2.erode(thresh, None, iterations=2)
        thresh = cv2.dilate(thresh, None, iterations=2)

        # find contours in thresholded image, then grab the largest one
        cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        c = max(cnts, key=cv2.contourArea)

        # find the extreme points
        extLeft = tuple(c[c[:, :, 0].argmin()][0])
        extRight = tuple(c[c[:, :, 0].argmax()][0])
        extTop = tuple(c[c[:, :, 1].argmin()][0])
        extBot = tuple(c[c[:, :, 1].argmax()][0])

        ADD_PIXELS = add_pixels_value
        new_img = img[extTop[1]-ADD_PIXELS:extBot[1]+ADD_PIXELS, extLeft[0]-ADD_PIXELS:extRight[0]+ADD_PIXELS].copy()
        set_new.append(new_img)

    return np.array(set_new)

Let's look at example what this function will do with MRI scans:

In [12]:
img = cv2.imread('brain_tumor_dataset/yes/Y108.jpg')
img = cv2.resize(
            img,
            dsize=IMG_SIZE,
            interpolation=cv2.INTER_CUBIC
        )
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)

# threshold the image, then perform a series of erosions +
# dilations to remove any small regions of noise
thresh = cv2.threshold(gray, 45, 255, cv2.THRESH_BINARY)[1]
thresh = cv2.erode(thresh, None, iterations=2)
thresh = cv2.dilate(thresh, None, iterations=2)

# find contours in thresholded image, then grab the largest one
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = max(cnts, key=cv2.contourArea)

# find the extreme points
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])

# add contour on the image
img_cnt = cv2.drawContours(img.copy(), [c], -1, (0, 255, 255), 4)

# add extreme points
img_pnt = cv2.circle(img_cnt.copy(), extLeft, 8, (0, 0, 255), -1)
img_pnt = cv2.circle(img_pnt, extRight, 8, (0, 255, 0), -1)
img_pnt = cv2.circle(img_pnt, extTop, 8, (255, 0, 0), -1)
img_pnt = cv2.circle(img_pnt, extBot, 8, (255, 255, 0), -1)

# crop
ADD_PIXELS = 0
new_img = img[extTop[1]-ADD_PIXELS:extBot[1]+ADD_PIXELS, extLeft[0]-ADD_PIXELS:extRight[0]+ADD_PIXELS].copy()
In [13]:
plt.figure(figsize=(15,6))
plt.subplot(141)
plt.imshow(img)
plt.xticks([])
plt.yticks([])
plt.title('Step 1. Get the original image')
plt.subplot(142)
plt.imshow(img_cnt)
plt.xticks([])
plt.yticks([])
plt.title('Step 2. Find the biggest contour')
plt.subplot(143)
plt.imshow(img_pnt)
plt.xticks([])
plt.yticks([])
plt.title('Step 3. Find the extreme points')
plt.subplot(144)
plt.imshow(new_img)
plt.xticks([])
plt.yticks([])
plt.title('Step 4. Crop the image')
plt.show()
In [14]:
# apply this for each set
X_train_crop = crop_imgs(set_name=X_train)
X_val_crop = crop_imgs(set_name=X_val)
X_test_crop = crop_imgs(set_name=X_test)
/Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages/ipykernel_launcher.py:31: VisibleDeprecationWarning:

Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray

In [15]:
plot_samples(X_train_crop, y_train, labels, 10)
In [16]:
def save_new_images(x_set, y_set, folder_name):
    i = 0
    for (img, imclass) in zip(x_set, y_set):
        if imclass == 0:
            cv2.imwrite(folder_name+'NO/'+str(i)+'.jpg', img)
        else:
            cv2.imwrite(folder_name+'YES/'+str(i)+'.jpg', img)
        i += 1
In [17]:
# saving new images to the folder
!mkdir TRAIN_CROP TEST_CROP VAL_CROP TRAIN_CROP/YES TRAIN_CROP/NO TEST_CROP/YES TEST_CROP/NO VAL_CROP/YES VAL_CROP/NO

save_new_images(X_train_crop, y_train, folder_name='TRAIN_CROP/')
save_new_images(X_val_crop, y_val, folder_name='VAL_CROP/')
save_new_images(X_test_crop, y_test, folder_name='TEST_CROP/')
mkdir: TRAIN_CROP: File exists
mkdir: TEST_CROP: File exists
mkdir: VAL_CROP: File exists
mkdir: TRAIN_CROP/YES: File exists
mkdir: TRAIN_CROP/NO: File exists
mkdir: TEST_CROP/YES: File exists
mkdir: TEST_CROP/NO: File exists
mkdir: VAL_CROP/YES: File exists
mkdir: VAL_CROP/NO: File exists

The next step would be resizing images to (224,224) and applying preprocessing needed for VGG-16 model input.

In [18]:
def preprocess_imgs(set_name, img_size):
    """
    Resize and apply VGG-15 preprocessing
    """
    set_new = []
    for img in set_name:
        img = cv2.resize(
            img,
            dsize=img_size,
            interpolation=cv2.INTER_CUBIC
        )
        set_new.append(preprocess_input(img))
    return np.array(set_new)
In [19]:
X_train_prep = preprocess_imgs(set_name=X_train_crop, img_size=IMG_SIZE)
X_test_prep = preprocess_imgs(set_name=X_test_crop, img_size=IMG_SIZE)
X_val_prep = preprocess_imgs(set_name=X_val_crop, img_size=IMG_SIZE)
In [20]:
 plot_samples(X_train_prep, y_train, labels, 10)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

4. CNN Model

I was using Transfer Learning with VGG-16 architecture , xception,InceptionV3 and weights as a base model.

4.1. Data Augmentation

Since I had small data set I used the technique called Data Augmentation which helps to "increase" the size of training set.

4.1.1. Demo

That's the example from one image how does augmentation look like.

In [21]:
# set the paramters we want to change randomly
demo_datagen = ImageDataGenerator(
    rotation_range=15,
    width_shift_range=0.05,
    height_shift_range=0.05,
    rescale=1./255,
    shear_range=0.05,
    brightness_range=[0.1, 1.5],
    horizontal_flip=True,
    vertical_flip=True
)
In [22]:
os.mkdir('preview')
x = X_train_crop[0]  
x = x.reshape((1,) + x.shape) 

i = 0
for batch in demo_datagen.flow(x, batch_size=1, save_to_dir='preview', save_prefix='aug_img', save_format='jpg'):
    i += 1
    if i > 20:
        break 
---------------------------------------------------------------------------
FileExistsError                           Traceback (most recent call last)
<ipython-input-22-182c6483d94d> in <module>
----> 1 os.mkdir('preview')
      2 x = X_train_crop[0]
      3 x = x.reshape((1,) + x.shape)
      4 
      5 i = 0

FileExistsError: [Errno 17] File exists: 'preview'
In [23]:
plt.imshow(X_train_crop[0])
plt.xticks([])
plt.yticks([])
plt.title('Original Image')
plt.show()

plt.figure(figsize=(15,6))
i = 1
for img in os.listdir('preview/'):
    img = cv2.cv2.imread('preview/' + img)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    plt.subplot(3,7,i)
    plt.imshow(img)
    plt.xticks([])
    plt.yticks([])
    i += 1
    if i > 3*7:
        break
plt.suptitle('Augemented Images')
plt.show()
In [24]:
!rm -rf preview/
In [26]:
TRAIN_DIR = 'TRAIN_CROP/'
VAL_DIR = 'VAL_CROP/'
TEST_DIR = 'TEST_CROP/'

train_datagen = ImageDataGenerator(
    rotation_range=15,
    width_shift_range=0.1,
    height_shift_range=0.1,
    shear_range=0.1,
    brightness_range=[0.5, 1.5],
    horizontal_flip=True,
    vertical_flip=True,
    preprocessing_function=preprocess_input
)

test_datagen = ImageDataGenerator(
    preprocessing_function=preprocess_input
)


train_generator = train_datagen.flow_from_directory(
    TRAIN_DIR,
    color_mode='rgb',
    target_size=IMG_SIZE,
    batch_size=32,
    class_mode='binary',
    seed=RANDOM_SEED
)


validation_generator = test_datagen.flow_from_directory(
    VAL_DIR,
    color_mode='rgb',
    target_size=IMG_SIZE,
    batch_size=16,
    class_mode='binary',
    seed=RANDOM_SEED
)

test_generator = test_datagen.flow_from_directory(
    TEST_DIR,
    color_mode='rgb',
    target_size=IMG_SIZE,
    batch_size=16,
    class_mode='binary',
    seed=RANDOM_SEED
)
Found 193 images belonging to 2 classes.
Found 50 images belonging to 2 classes.
Found 10 images belonging to 2 classes.

Transfer Learning Tutorial

Transfer Learning

In practice, very few people train an entire Convolutional Network from scratch (with random initialization), because it is relatively rare to have a dataset of sufficient size. Instead, it is common to pretrain a ConvNet on a very large dataset (e.g. ImageNet, which contains 1.2 million images with 1000 categories), and then use the ConvNet either as an initialization or a fixed feature extractor for the task of interest.

We always hear that we do not have to reinvent the wheel. Well, this is always true. Why do not we work and climb over the giant shoulders? Why do not we build something even if we change it a bit? Well, that's not a theft. In fact, everything on the Internet without a license is open source. You can deal with a simple modification that you can get on your next research paper, but the purpose is to understand what has been completed and not just use it.

These two major Transfer learning scenarios look as follows:

Finetuning the convnet: Instead of random initializaion, we initialize the network with a pretrained network, like the one that is trained on imagenet 1000 dataset. Rest of the training looks as usual.

ConvNet as fixed feature extractor: Here, we will freeze the weights for all of the network except that of the final fully connected layer. This last fully connected layer is replaced with a new one with random weights and only this layer is trained.

I was wondering a few days ago if I had 1000 pictures of a dog in a folder , but I do not know the number of types of dogs inside. just 1000 pictures only, no more and no less with out topic or file name or folder name or just a small label . how can i apply classifer method on it ? This was a big problem so I thought of some solutions that might be logical for most of us, namely, Transefer learning . What if CNN was used and at the last activation Function was removed ? The output must be Tensors * Yes, a large array of matrices carry the standard Features of each dog and that is what I want. Now I can use the compilation method and the elbow method to see how many dogs are in the picture Then we apply one of the dimensions reduction algorithms Like (PCA) and use the k-nn algorithm, and then we will have half of the non-supervisory Deep learning algorithm called K-CNN. I do not know What do you think ?

Well, it's a great idea but unfortunately there are people before me who wrote the paper but it does not matter I'll invent something else and I will write a research paper someday Class Agnostic Image Common Object Detection

Transefer Learning

In [28]:
# load base model
from tensorflow.keras.applications.resnet import ResNet50
resnet50_x = ResNet50(weights='imagenet')
weights = ResNet50(weights='imagenet', include_top=False)
In [29]:
# load base model
InceptionV3_weight_path = 'inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'
inceptionV3 = InceptionV3(
     weights=InceptionV3_weight_path,
    include_top=False, 
    input_shape=IMG_SIZE + (3,)
)
In [30]:
# load base model
vgg16_weight_path = 'vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'
vgg = VGG16(
    weights=vgg16_weight_path,
    include_top=False, 
    input_shape=IMG_SIZE + (3,)
)
In [31]:
pip install umap-learn
Requirement already satisfied: umap-learn in /Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages (0.4.6)
Requirement already satisfied: numba!=0.47,>=0.46 in /Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages (from umap-learn) (0.51.2)
Requirement already satisfied: scipy>=1.3.1 in /Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages (from umap-learn) (1.5.2)
Requirement already satisfied: scikit-learn>=0.20 in /Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages (from umap-learn) (0.23.2)
Requirement already satisfied: numpy>=1.17 in /Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages (from umap-learn) (1.19.1)
Requirement already satisfied: setuptools in /Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages (from numba!=0.47,>=0.46->umap-learn) (50.3.0.post20201006)
Requirement already satisfied: llvmlite<0.35,>=0.34.0.dev0 in /Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages (from numba!=0.47,>=0.46->umap-learn) (0.34.0)
Requirement already satisfied: joblib>=0.11 in /Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages (from scikit-learn>=0.20->umap-learn) (0.17.0)
Requirement already satisfied: threadpoolctl>=2.0.0 in /Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages (from scikit-learn>=0.20->umap-learn) (2.1.0)
Note: you may need to restart the kernel to use updated packages.
In [32]:
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import math
import cv2
import matplotlib.pyplot as plt
import os
import seaborn as sns
import umap
from PIL import Image
from scipy import misc
from os import listdir
from os.path import isfile, join
import numpy as np
from scipy import misc
from random import shuffle
from collections import Counter
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
import tensorflow as tf
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.utils.np_utils import to_categorical
from keras.layers import Input
In [33]:
import os
import sys
import random
import warnings

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt

from tqdm import tqdm
from itertools import chain
from skimage.io import imread, imshow, imread_collection, concatenate_images
from skimage.transform import resize
from skimage.morphology import label

from keras.models import Model, load_model
from keras.layers import Input
from keras.layers.core import Dropout, Lambda
from keras.layers.convolutional import Conv2D, Conv2DTranspose
from keras.layers.pooling import MaxPooling2D
from keras.layers.merge import concatenate
from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras import backend as K
import keras

I also love the scholars to learn from them and their experiences, and to give me stories about them and their experiences in life. I like their way of telling stories and giving me information, they sing for hours of hard and long work

This is exactly what happens in a model that has been trained on a lot of things. What we are doing now is to give out only two of the 1000 things that we know and ask. Do you know them? Well, what would happen if we did not use weights for the model? In that case it will be a normal model all you do is put it in your form and add the final layer Flatten to initialize the model for the classification process

VGG-16

In [34]:
# plot feature map of first conv layer for given image
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.models import Model
from matplotlib import pyplot 
from numpy import expand_dims


f = plt.figure(figsize=(16,16))
# load the modelf = plt.figure(figsize=(10,3))
model = VGG16()
# redefine model to output right after the first hidden layer
model = Model(inputs=model.inputs, outputs=model.layers[1].output)
model.summary()
# load the image with the required shape
# convert the image to an array
img = img_to_array(X_val_prep[43])
# expand dimensions so that it represents a single 'sample'
img = expand_dims(img, axis=0)
# prepare the image (e.g. scale pixel values for the vgg)
img = preprocess_input(img)
# get feature map for first hidden layer
feature_maps = model.predict(img)
# plot all 64 maps in an 8x8 squares
square = 8
ix = 1
for _ in range(square):
	for _ in range(square):
		# specify subplot and turn of axis
		ax = pyplot.subplot(square, square, ix)
		ax.set_xticks([])
		ax.set_yticks([])
		# plot filter channel in grayscale
		pyplot.imshow(feature_maps[0, :, :, ix-1], cmap='viridis')
		ix += 1
# show the figure
pyplot.show()
Model: "functional_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_7 (InputLayer)         [(None, 224, 224, 3)]     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
=================================================================
Total params: 1,792
Trainable params: 1,792
Non-trainable params: 0
_________________________________________________________________
In [35]:
NUM_CLASSES = 1

vgg16 = Sequential()
vgg16.add(vgg)
vgg16.add(layers.Dropout(0.3))
vgg16.add(layers.Flatten())
vgg16.add(layers.Dropout(0.5))
vgg16.add(layers.Dense(NUM_CLASSES, activation='sigmoid'))

vgg16.layers[0].trainable = False

vgg16.compile(
    loss='binary_crossentropy',
    optimizer=RMSprop(lr=1e-4),
    metrics=['accuracy']
)
vgg16.compile(loss='binary_crossentropy', optimizer=keras.optimizers.Adam(lr=0.0003, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False), metrics=["accuracy"])

vgg16.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
vgg16 (Functional)           (None, 7, 7, 512)         14714688  
_________________________________________________________________
dropout (Dropout)            (None, 7, 7, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 25088)             0         
_________________________________________________________________
dense (Dense)                (None, 1)                 25089     
=================================================================
Total params: 14,739,777
Trainable params: 25,089
Non-trainable params: 14,714,688
_________________________________________________________________
In [36]:
# visualize feature maps output from each block in the vgg model
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.models import Model
import matplotlib.pyplot as plt
from numpy import expand_dims




# load the model
model = VGG16()
# redefine model to output right after the first hidden layer
ixs = [2, 5, 9, 13, 17]
outputs = [model.layers[i].output for i in ixs]
model = Model(inputs=model.inputs, outputs=outputs)
# load the image with the required shape
# convert the image to an array
img = img_to_array(X_val_prep[43])
# expand dimensions so that it represents a single 'sample'
img = expand_dims(img, axis=0)
# prepare the image (e.g. scale pixel values for the vgg)
img = preprocess_input(img)
# get feature map for first hidden layer
feature_maps = model.predict(img)
# plot the output from each block
square = 8
for fmap in feature_maps:
	# plot all 64 maps in an 8x8 squares
	ix = 1
	for _ in range(square):
		plt.figure(figsize=(64,64))
		for _ in range(square):
           

			# specify subplot and turn of axis
			ax = pyplot.subplot(square, square, ix)
			ax.set_xticks([])
			ax.set_yticks([])
			
			# plot filter channel in grayscale
			plt.imshow(fmap[0, :, :, ix-1], cmap='viridis')
			ix += 1
	# show the figure

        
	plt.show()
In [39]:
import time

start = time.time()

vgg16_history = vgg16.fit_generator(
    train_generator,
    epochs=30,
    validation_data=validation_generator,
)


end = time.time()
print(end - start)
Epoch 1/30
7/7 [==============================] - 69s 10s/step - loss: 2.6463 - accuracy: 0.8135 - val_loss: 1.3084 - val_accuracy: 0.8000
Epoch 2/30
7/7 [==============================] - 77s 11s/step - loss: 2.5198 - accuracy: 0.7772 - val_loss: 2.1840 - val_accuracy: 0.7800
Epoch 3/30
7/7 [==============================] - 73s 10s/step - loss: 4.0539 - accuracy: 0.7150 - val_loss: 2.7126 - val_accuracy: 0.7800
Epoch 4/30
7/7 [==============================] - 62s 9s/step - loss: 2.8723 - accuracy: 0.7513 - val_loss: 2.5520 - val_accuracy: 0.7800
Epoch 5/30
7/7 [==============================] - 63s 9s/step - loss: 2.3648 - accuracy: 0.7927 - val_loss: 1.2708 - val_accuracy: 0.8800
Epoch 6/30
7/7 [==============================] - 77s 11s/step - loss: 2.9430 - accuracy: 0.7772 - val_loss: 1.5016 - val_accuracy: 0.8000
Epoch 7/30
7/7 [==============================] - 68s 10s/step - loss: 2.5948 - accuracy: 0.7409 - val_loss: 2.5033 - val_accuracy: 0.8000
Epoch 8/30
7/7 [==============================] - 68s 10s/step - loss: 2.6761 - accuracy: 0.7772 - val_loss: 1.3692 - val_accuracy: 0.8400
Epoch 9/30
7/7 [==============================] - 70s 10s/step - loss: 2.2789 - accuracy: 0.8238 - val_loss: 1.3026 - val_accuracy: 0.9000
Epoch 10/30
7/7 [==============================] - 67s 10s/step - loss: 1.9789 - accuracy: 0.8290 - val_loss: 2.1663 - val_accuracy: 0.8400
Epoch 11/30
7/7 [==============================] - 66s 9s/step - loss: 2.6462 - accuracy: 0.7876 - val_loss: 1.7286 - val_accuracy: 0.8400
Epoch 12/30
7/7 [==============================] - 68s 10s/step - loss: 3.1632 - accuracy: 0.7720 - val_loss: 1.3658 - val_accuracy: 0.8600
Epoch 13/30
7/7 [==============================] - 77s 11s/step - loss: 2.0390 - accuracy: 0.8238 - val_loss: 1.9709 - val_accuracy: 0.8400
Epoch 14/30
7/7 [==============================] - 68s 10s/step - loss: 1.7105 - accuracy: 0.8394 - val_loss: 2.0149 - val_accuracy: 0.8400
Epoch 15/30
7/7 [==============================] - 69s 10s/step - loss: 2.4075 - accuracy: 0.8135 - val_loss: 1.4382 - val_accuracy: 0.9000
Epoch 16/30
7/7 [==============================] - 68s 10s/step - loss: 2.6892 - accuracy: 0.7927 - val_loss: 1.3774 - val_accuracy: 0.9000
Epoch 17/30
7/7 [==============================] - 68s 10s/step - loss: 2.7934 - accuracy: 0.7824 - val_loss: 3.8056 - val_accuracy: 0.6800
Epoch 18/30
7/7 [==============================] - 69s 10s/step - loss: 2.8551 - accuracy: 0.7720 - val_loss: 3.9516 - val_accuracy: 0.6600
Epoch 19/30
7/7 [==============================] - 67s 10s/step - loss: 2.4589 - accuracy: 0.7720 - val_loss: 1.8901 - val_accuracy: 0.8400
Epoch 20/30
7/7 [==============================] - 121s 17s/step - loss: 1.8027 - accuracy: 0.8394 - val_loss: 1.6836 - val_accuracy: 0.8400
Epoch 21/30
7/7 [==============================] - 77s 11s/step - loss: 1.7453 - accuracy: 0.8446 - val_loss: 1.3959 - val_accuracy: 0.8600
Epoch 22/30
7/7 [==============================] - 68s 10s/step - loss: 1.7618 - accuracy: 0.8601 - val_loss: 1.9103 - val_accuracy: 0.8200
Epoch 23/30
7/7 [==============================] - 67s 10s/step - loss: 1.5955 - accuracy: 0.8705 - val_loss: 1.8772 - val_accuracy: 0.8200
Epoch 24/30
7/7 [==============================] - 78s 11s/step - loss: 2.5780 - accuracy: 0.8083 - val_loss: 1.8522 - val_accuracy: 0.8200
Epoch 25/30
7/7 [==============================] - 80s 11s/step - loss: 1.7894 - accuracy: 0.8394 - val_loss: 1.9602 - val_accuracy: 0.8200
Epoch 26/30
7/7 [==============================] - 71s 10s/step - loss: 1.6323 - accuracy: 0.8394 - val_loss: 2.3062 - val_accuracy: 0.8200
Epoch 27/30
7/7 [==============================] - 81s 12s/step - loss: 1.7384 - accuracy: 0.8497 - val_loss: 2.4348 - val_accuracy: 0.7800
Epoch 28/30
7/7 [==============================] - 79s 11s/step - loss: 1.8454 - accuracy: 0.8446 - val_loss: 3.2329 - val_accuracy: 0.7800
Epoch 29/30
7/7 [==============================] - 95s 14s/step - loss: 1.6626 - accuracy: 0.8756 - val_loss: 3.0816 - val_accuracy: 0.7800
Epoch 30/30
7/7 [==============================] - 91s 13s/step - loss: 2.5359 - accuracy: 0.8187 - val_loss: 2.8968 - val_accuracy: 0.7800
2526.0621333122253

Calculate Metric

In [104]:
# validate on val set
predictions = vgg16.predict(X_test_prep)
predictions = [1 if x>0.5 else 0 for x in predictions]

_, train_acc = vgg16.evaluate(X_val_prep, y_val, verbose=0)
_, test_acc = vgg16.evaluate(X_test_prep, y_test, verbose=0)
In [105]:
pyplot.figure(figsize=(12,12))
# plot loss during training
pyplot.subplot(211)
pyplot.title('Vgg16 Loss')
pyplot.plot(vgg16_history.history['loss'], label='train')
pyplot.plot(vgg16_history.history['val_loss'], label='Validation')
pyplot.legend()
# plot accuracy during training
pyplot.subplot(212)
pyplot.title('Vgg16 Accuracy')
pyplot.plot(vgg16_history.history['accuracy'], label='train')
pyplot.plot(vgg16_history.history['val_accuracy'], label='Validation')
pyplot.legend()
pyplot.show()
In [106]:
print('Train: %.3f, Test: %.3f' % (train_acc, test_acc))
Train: 0.840, Test: 0.800
In [107]:
from sklearn.datasets import make_circles
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import cohen_kappa_score
from sklearn.metrics import roc_auc_score
from sklearn.metrics import confusion_matrix
from keras.models import Sequential
from keras.layers import Dense

# accuracy: (tp + tn) / (p + n)
accuracy = accuracy_score(y_test, predictions)
print('Accuracy: %f' % accuracy)
# precision tp / (tp + fp)
precision = precision_score(y_test, predictions)
print('Precision: %f' % precision)
# recall: tp / (tp + fn)
recall = recall_score(y_test, predictions)
print('Recall: %f' % recall)
# f1: 2 tp / (2 tp + fp + fn)
f1 = f1_score(y_test, predictions)
print('F1 score: %f' % f1)
Accuracy: 0.800000
Precision: 1.000000
Recall: 0.600000
F1 score: 0.750000
In [108]:
kappa = cohen_kappa_score(y_test, predictions)
print('Cohens kappa: %f' % kappa)
# ROC AUC
auc = roc_auc_score(y_test, predictions)
print('ROC AUC: %f' % auc)
# confusion matrix
matrix = confusion_matrix(y_test, predictions)
print(matrix)
cm = plot_confusion_matrix(matrix, classes = list(labels.items()), normalize=False)
Cohens kappa: 0.600000
ROC AUC: 0.800000
[[5 0]
 [2 3]]

InceptionV3

In [45]:
NUM_CLASSES = 1

inception_v3 = Sequential()
inception_v3.add(inceptionV3)
inception_v3.add(layers.Dropout(0.3))
inception_v3.add(layers.Flatten())
inception_v3.add(layers.Dropout(0.5))
inception_v3.add(layers.Dense(NUM_CLASSES, activation='sigmoid'))

inception_v3.layers[0].trainable = False

inception_v3.compile(
    loss='binary_crossentropy',
    optimizer=RMSprop(lr=1e-4),
    metrics=['accuracy']
)

inception_v3.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
inception_v3 (Functional)    (None, 5, 5, 2048)        21802784  
_________________________________________________________________
dropout_2 (Dropout)          (None, 5, 5, 2048)        0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 51200)             0         
_________________________________________________________________
dropout_3 (Dropout)          (None, 51200)             0         
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 51201     
=================================================================
Total params: 21,853,985
Trainable params: 51,201
Non-trainable params: 21,802,784
_________________________________________________________________
In [46]:
import time

start = time.time()

inception_v3_history = inception_v3.fit_generator(
    train_generator,
    epochs=30,
    validation_data=validation_generator,
)

end = time.time()
print(end - start)
Epoch 1/30
7/7 [==============================] - 15s 2s/step - loss: 19.4183 - accuracy: 0.5233 - val_loss: 5.8246 - val_accuracy: 0.5000
Epoch 2/30
7/7 [==============================] - 13s 2s/step - loss: 14.5444 - accuracy: 0.5440 - val_loss: 3.8091 - val_accuracy: 0.5800
Epoch 3/30
7/7 [==============================] - 13s 2s/step - loss: 14.4462 - accuracy: 0.5492 - val_loss: 3.8254 - val_accuracy: 0.6200
Epoch 4/30
7/7 [==============================] - 13s 2s/step - loss: 16.3324 - accuracy: 0.4870 - val_loss: 11.1961 - val_accuracy: 0.6000
Epoch 5/30
7/7 [==============================] - 13s 2s/step - loss: 13.4240 - accuracy: 0.5751 - val_loss: 5.2393 - val_accuracy: 0.5800
Epoch 6/30
7/7 [==============================] - 14s 2s/step - loss: 15.1946 - accuracy: 0.5337 - val_loss: 4.2598 - val_accuracy: 0.6400
Epoch 7/30
7/7 [==============================] - 15s 2s/step - loss: 10.9071 - accuracy: 0.5959 - val_loss: 3.3498 - val_accuracy: 0.6400
Epoch 8/30
7/7 [==============================] - 14s 2s/step - loss: 13.6096 - accuracy: 0.5855 - val_loss: 4.4986 - val_accuracy: 0.6400
Epoch 9/30
7/7 [==============================] - 14s 2s/step - loss: 11.6534 - accuracy: 0.6010 - val_loss: 2.8512 - val_accuracy: 0.7000
Epoch 10/30
7/7 [==============================] - 15s 2s/step - loss: 13.8073 - accuracy: 0.5233 - val_loss: 3.2328 - val_accuracy: 0.6600
Epoch 11/30
7/7 [==============================] - 14s 2s/step - loss: 12.6566 - accuracy: 0.5751 - val_loss: 3.6331 - val_accuracy: 0.6600
Epoch 12/30
7/7 [==============================] - 15s 2s/step - loss: 12.9354 - accuracy: 0.6425 - val_loss: 2.8501 - val_accuracy: 0.6600
Epoch 13/30
7/7 [==============================] - 16s 2s/step - loss: 10.3403 - accuracy: 0.6321 - val_loss: 3.3383 - val_accuracy: 0.6800
Epoch 14/30
7/7 [==============================] - 15s 2s/step - loss: 11.2997 - accuracy: 0.6528 - val_loss: 3.7814 - val_accuracy: 0.7000
Epoch 15/30
7/7 [==============================] - 16s 2s/step - loss: 11.5296 - accuracy: 0.5699 - val_loss: 3.4495 - val_accuracy: 0.7000
Epoch 16/30
7/7 [==============================] - 15s 2s/step - loss: 13.1110 - accuracy: 0.5751 - val_loss: 3.1502 - val_accuracy: 0.7000
Epoch 17/30
7/7 [==============================] - 16s 2s/step - loss: 7.5904 - accuracy: 0.6943 - val_loss: 2.4943 - val_accuracy: 0.7000
Epoch 18/30
7/7 [==============================] - 15s 2s/step - loss: 9.2061 - accuracy: 0.6062 - val_loss: 3.0405 - val_accuracy: 0.6600
Epoch 19/30
7/7 [==============================] - 16s 2s/step - loss: 8.4635 - accuracy: 0.6736 - val_loss: 4.7057 - val_accuracy: 0.6400
Epoch 20/30
7/7 [==============================] - 16s 2s/step - loss: 13.1625 - accuracy: 0.5959 - val_loss: 2.8386 - val_accuracy: 0.7000
Epoch 21/30
7/7 [==============================] - 15s 2s/step - loss: 9.3578 - accuracy: 0.6373 - val_loss: 3.1167 - val_accuracy: 0.6600
Epoch 22/30
7/7 [==============================] - 18s 3s/step - loss: 9.2700 - accuracy: 0.6373 - val_loss: 2.8632 - val_accuracy: 0.7000
Epoch 23/30
7/7 [==============================] - 16s 2s/step - loss: 10.4681 - accuracy: 0.6321 - val_loss: 3.5797 - val_accuracy: 0.7000
Epoch 24/30
7/7 [==============================] - 16s 2s/step - loss: 10.9566 - accuracy: 0.6477 - val_loss: 6.7830 - val_accuracy: 0.6000
Epoch 25/30
7/7 [==============================] - 16s 2s/step - loss: 9.9425 - accuracy: 0.6425 - val_loss: 3.1686 - val_accuracy: 0.7600
Epoch 26/30
7/7 [==============================] - 16s 2s/step - loss: 11.6803 - accuracy: 0.6010 - val_loss: 5.5670 - val_accuracy: 0.6000
Epoch 27/30
7/7 [==============================] - 16s 2s/step - loss: 12.1145 - accuracy: 0.5855 - val_loss: 3.8253 - val_accuracy: 0.6800
Epoch 28/30
7/7 [==============================] - 16s 2s/step - loss: 9.8637 - accuracy: 0.6269 - val_loss: 2.5038 - val_accuracy: 0.6800
Epoch 29/30
7/7 [==============================] - 16s 2s/step - loss: 12.1009 - accuracy: 0.5803 - val_loss: 2.2595 - val_accuracy: 0.7000
Epoch 30/30
7/7 [==============================] - 16s 2s/step - loss: 10.0688 - accuracy: 0.6321 - val_loss: 3.8624 - val_accuracy: 0.6400
541.2393078804016
In [99]:
# validate on val set
predictions = inception_v3.predict(X_test_prep)
predictions = [1 if x>0.5 else 0 for x in predictions]

_, train_acc = inception_v3.evaluate(X_val_prep, y_val, verbose=0)
_, test_acc = inception_v3.evaluate(X_test_prep, y_test, verbose=0)
In [100]:
pyplot.figure(figsize=(12,12))
# plot loss during training
pyplot.subplot(211)
pyplot.title('Inception V3 Loss')
pyplot.plot(inception_v3_history.history['loss'], label='train')
pyplot.plot(inception_v3_history.history['val_loss'], label='Validation')
pyplot.legend()
# plot accuracy during training
pyplot.subplot(212)
pyplot.title('Inception V3 Accuracy')
pyplot.plot(inception_v3_history.history['accuracy'], label='train')
pyplot.plot(inception_v3_history.history['val_accuracy'], label='Validation')
pyplot.legend()
pyplot.show()
In [101]:
print('Train: %.3f, Test: %.3f' % (train_acc, test_acc))
Train: 0.660, Test: 0.500
In [102]:
from sklearn.datasets import make_circles
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import cohen_kappa_score
from sklearn.metrics import roc_auc_score
from sklearn.metrics import confusion_matrix
from keras.models import Sequential
from keras.layers import Dense

# accuracy: (tp + tn) / (p + n)
accuracy = accuracy_score(y_test, predictions)
print('Accuracy: %f' % accuracy)
# precision tp / (tp + fp)
precision = precision_score(y_test, predictions)
print('Precision: %f' % precision)
# recall: tp / (tp + fn)
recall = recall_score(y_test, predictions)
print('Recall: %f' % recall)
# f1: 2 tp / (2 tp + fp + fn)
f1 = f1_score(y_test, predictions)
print('F1 score: %f' % f1)
Accuracy: 0.500000
Precision: 0.500000
Recall: 0.200000
F1 score: 0.285714
In [103]:
kappa = cohen_kappa_score(y_test, predictions)
print('Cohens kappa: %f' % kappa)
# ROC AUC
auc = roc_auc_score(y_test, predictions)
print('ROC AUC: %f' % auc)
# confusion matrix
matrix = confusion_matrix(y_test, predictions)
print(matrix)
cm = plot_confusion_matrix(matrix, classes = list(labels.items()), normalize=False)
Cohens kappa: 0.000000
ROC AUC: 0.500000
[[4 1]
 [4 1]]

RESNET50

In [52]:
NUM_CLASSES = 1

resnet50 = Sequential()
resnet50.add(resnet50_x)
resnet50.add(layers.Dropout(0.3))
resnet50.add(layers.Flatten())
resnet50.add(layers.Dropout(0.5))
resnet50.add(layers.Dense(NUM_CLASSES, activation='sigmoid'))

resnet50.layers[0].trainable = False

resnet50.compile(
    loss='binary_crossentropy',
    optimizer=RMSprop(lr=1e-4),
    metrics=['accuracy']
)
resnet50.compile(loss='binary_crossentropy', optimizer=keras.optimizers.Adam(lr=0.0003, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False), metrics=["accuracy"])

resnet50.summary()
Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
resnet50 (Functional)        (None, 1000)              25636712  
_________________________________________________________________
dropout_4 (Dropout)          (None, 1000)              0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 1000)              0         
_________________________________________________________________
dropout_5 (Dropout)          (None, 1000)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 1001      
=================================================================
Total params: 25,637,713
Trainable params: 1,001
Non-trainable params: 25,636,712
_________________________________________________________________
In [54]:
import time

start = time.time()

resnet50_history = resnet50.fit_generator(
    train_generator,
    epochs=30,
    validation_data=validation_generator,
)

end = time.time()
print(end - start)
Epoch 1/30
7/7 [==============================] - 23s 3s/step - loss: 0.6931 - accuracy: 0.5026 - val_loss: 0.6918 - val_accuracy: 0.5400
Epoch 2/30
7/7 [==============================] - 21s 3s/step - loss: 0.6923 - accuracy: 0.5181 - val_loss: 0.6915 - val_accuracy: 0.5400
Epoch 3/30
7/7 [==============================] - 22s 3s/step - loss: 0.6926 - accuracy: 0.5285 - val_loss: 0.6912 - val_accuracy: 0.5600
Epoch 4/30
7/7 [==============================] - 24s 3s/step - loss: 0.6931 - accuracy: 0.5389 - val_loss: 0.6910 - val_accuracy: 0.5600
Epoch 5/30
7/7 [==============================] - 27s 4s/step - loss: 0.6919 - accuracy: 0.5907 - val_loss: 0.6907 - val_accuracy: 0.5800
Epoch 6/30
7/7 [==============================] - 35s 5s/step - loss: 0.6933 - accuracy: 0.5596 - val_loss: 0.6904 - val_accuracy: 0.6000
Epoch 7/30
7/7 [==============================] - 32s 5s/step - loss: 0.6916 - accuracy: 0.5751 - val_loss: 0.6902 - val_accuracy: 0.6000
Epoch 8/30
7/7 [==============================] - 32s 5s/step - loss: 0.6902 - accuracy: 0.6010 - val_loss: 0.6899 - val_accuracy: 0.6200
Epoch 9/30
7/7 [==============================] - 31s 4s/step - loss: 0.6908 - accuracy: 0.5389 - val_loss: 0.6896 - val_accuracy: 0.6200
Epoch 10/30
7/7 [==============================] - 32s 5s/step - loss: 0.6887 - accuracy: 0.6114 - val_loss: 0.6893 - val_accuracy: 0.6800
Epoch 11/30
7/7 [==============================] - 28s 4s/step - loss: 0.6868 - accuracy: 0.6684 - val_loss: 0.6891 - val_accuracy: 0.7000
Epoch 12/30
7/7 [==============================] - 34s 5s/step - loss: 0.6906 - accuracy: 0.5959 - val_loss: 0.6888 - val_accuracy: 0.7000
Epoch 13/30
7/7 [==============================] - 32s 5s/step - loss: 0.6877 - accuracy: 0.6114 - val_loss: 0.6886 - val_accuracy: 0.7000
Epoch 14/30
7/7 [==============================] - 29s 4s/step - loss: 0.6904 - accuracy: 0.6218 - val_loss: 0.6884 - val_accuracy: 0.7000
Epoch 15/30
7/7 [==============================] - 30s 4s/step - loss: 0.6907 - accuracy: 0.5699 - val_loss: 0.6881 - val_accuracy: 0.7000
Epoch 16/30
7/7 [==============================] - 31s 4s/step - loss: 0.6888 - accuracy: 0.6321 - val_loss: 0.6878 - val_accuracy: 0.7000
Epoch 17/30
7/7 [==============================] - 27s 4s/step - loss: 0.6879 - accuracy: 0.6114 - val_loss: 0.6876 - val_accuracy: 0.7000
Epoch 18/30
7/7 [==============================] - 26s 4s/step - loss: 0.6848 - accuracy: 0.6995 - val_loss: 0.6873 - val_accuracy: 0.7000
Epoch 19/30
7/7 [==============================] - 30s 4s/step - loss: 0.6886 - accuracy: 0.6269 - val_loss: 0.6872 - val_accuracy: 0.7000
Epoch 20/30
7/7 [==============================] - 30s 4s/step - loss: 0.6885 - accuracy: 0.5751 - val_loss: 0.6869 - val_accuracy: 0.7000
Epoch 21/30
7/7 [==============================] - 33s 5s/step - loss: 0.6882 - accuracy: 0.5959 - val_loss: 0.6867 - val_accuracy: 0.7000
Epoch 22/30
7/7 [==============================] - 26s 4s/step - loss: 0.6844 - accuracy: 0.6477 - val_loss: 0.6865 - val_accuracy: 0.7000
Epoch 23/30
7/7 [==============================] - 29s 4s/step - loss: 0.6880 - accuracy: 0.6010 - val_loss: 0.6863 - val_accuracy: 0.6800
Epoch 24/30
7/7 [==============================] - 25s 4s/step - loss: 0.6873 - accuracy: 0.6218 - val_loss: 0.6862 - val_accuracy: 0.6600
Epoch 25/30
7/7 [==============================] - 26s 4s/step - loss: 0.6909 - accuracy: 0.5648 - val_loss: 0.6860 - val_accuracy: 0.6200
Epoch 26/30
7/7 [==============================] - 26s 4s/step - loss: 0.6883 - accuracy: 0.5907 - val_loss: 0.6859 - val_accuracy: 0.6200
Epoch 27/30
7/7 [==============================] - 29s 4s/step - loss: 0.6856 - accuracy: 0.6269 - val_loss: 0.6857 - val_accuracy: 0.6200
Epoch 28/30
7/7 [==============================] - 26s 4s/step - loss: 0.6861 - accuracy: 0.6114 - val_loss: 0.6856 - val_accuracy: 0.6200
Epoch 29/30
7/7 [==============================] - 27s 4s/step - loss: 0.6849 - accuracy: 0.6839 - val_loss: 0.6854 - val_accuracy: 0.6000
Epoch 30/30
7/7 [==============================] - 26s 4s/step - loss: 0.6860 - accuracy: 0.6321 - val_loss: 0.6852 - val_accuracy: 0.6000
955.9906158447266
In [110]:
# validate on val set
predictions = resnet50.predict(X_test_prep)
predictions = [1 if x>0.5 else 0 for x in predictions]

_, train_acc = resnet50.evaluate(X_val_prep, y_val, verbose=0)
_, test_acc = resnet50.evaluate(X_test_prep, y_test, verbose=0)
In [111]:
pyplot.figure(figsize=(12,12))
# plot loss during training
pyplot.subplot(211)
pyplot.title('ResNet50 Loss')
pyplot.plot(resnet50_history.history['loss'], label='train')
pyplot.plot(resnet50_history.history['val_loss'], label='Validation')
pyplot.legend()
# plot accuracy during training
pyplot.subplot(212)
pyplot.title('ResNet50 Accuracy')
pyplot.plot(resnet50_history.history['accuracy'], label='train')
pyplot.plot(resnet50_history.history['val_accuracy'], label='Validation')
pyplot.legend()
pyplot.show()
/Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages/ipykernel_launcher.py:14: UserWarning:

Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure.

In [57]:
print('Train: %.3f, Test: %.3f' % (train_acc, test_acc))
Train: 0.540, Test: 0.600
In [58]:
from sklearn.datasets import make_circles
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import cohen_kappa_score
from sklearn.metrics import roc_auc_score
from sklearn.metrics import confusion_matrix
from keras.models import Sequential
from keras.layers import Dense

# accuracy: (tp + tn) / (p + n)
accuracy = accuracy_score(y_test, predictions)
print('Accuracy: %f' % accuracy)
# precision tp / (tp + fp)
precision = precision_score(y_test, predictions)
print('Precision: %f' % precision)
# recall: tp / (tp + fn)
recall = recall_score(y_test, predictions)
print('Recall: %f' % recall)
# f1: 2 tp / (2 tp + fp + fn)
f1 = f1_score(y_test, predictions)
print('F1 score: %f' % f1)
Accuracy: 0.600000
Precision: 0.555556
Recall: 1.000000
F1 score: 0.714286
In [69]:
kappa = cohen_kappa_score(y_test, predictions)
print('Cohens kappa: %f' % kappa)
# ROC AUC
auc = roc_auc_score(y_test, predictions)
print('ROC AUC: %f' % auc)
# confusion matrix
matrix = confusion_matrix(y_test, predictions)
print(matrix)
cm = plot_confusion_matrix(matrix, classes = list(labels.items()), normalize=False)
Cohens kappa: 0.200000
ROC AUC: 0.600000
[[1 4]
 [0 5]]
/Users/ridhikhurana/opt/anaconda3/envs/deeplearning/lib/python3.7/site-packages/ipykernel_launcher.py:52: UserWarning:

Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure.

5. Conclusions

This project was a combination of CNN model classification problem (to predict wheter the subject has brain tumor or not) & Computer Vision problem (to automate the process of brain cropping from MRI scans). The final accuracy is much higher than 50% baseline (random guess). However, it could be increased by larger number of train images or through model hyperparameters tuning.

Well we've done very well just about a cycle brother just that it's a record I think I'm happy with that result and I'm also happy to share some science with you. Now it is your turn to use lots and lots of your own models, you can publish your next research paper entitled Transefer Learning . This was a great lesson and thank you for following up and thank this man for his efforts at this kernel

Ruslan Klymentiev